package com.vhans.db.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vhans.core.utils.StringUtils;
import com.vhans.core.domain.BTag;
import com.vhans.core.domain.BTagText;
import com.vhans.db.mapper.BQuizMapper;
import com.vhans.db.mapper.BRecordMapper;
import com.vhans.db.mapper.BTagMapper;
import com.vhans.db.mapper.BTagTextMapper;
import com.vhans.db.model.dto.ConditionDTO;
import com.vhans.db.model.dto.tag.TagDTO;
import com.vhans.db.model.vo.quiz.QuizConditionList;
import com.vhans.db.model.vo.quiz.QuizConditionVO;
import com.vhans.db.model.vo.record.RecordConditionList;
import com.vhans.db.model.vo.record.RecordConditionVO;
import com.vhans.db.model.vo.tag.*;
import com.vhans.db.service.IBTagService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 标签业务接口实现类
 *
 * @author vhans
 **/
@Service
public class BTagServiceImpl extends ServiceImpl<BTagMapper, BTag> implements IBTagService {

    @Autowired
    private BTagMapper tagMapper;

    @Autowired
    private BTagTextMapper tagTextMapper;

    @Autowired
    private BRecordMapper recordMapper;

    @Autowired
    private BQuizMapper quizMapper;

    @Override
    public List<TagVO> listTagVO(ConditionDTO condition) {
        Assert.isFalse(StringUtils.isNull(condition.getType()), "未指定标签类型");
        Assert.isTrue(condition.getType() == 1 || condition.getType() == 2,
                "指定标签类型错误");
        return tagMapper.selectTagVO(condition);
    }

    @Override
    public void addTag(TagDTO tag) {
        // 标签是否存在
        BTag existTag = tagMapper.selectOne(new LambdaQueryWrapper<BTag>()
                .select(BTag::getId)
                .ne(BTag::getId, tag.getId())
                .eq(BTag::getTagName, tag.getTagName()));
        Assert.isNull(existTag, tag.getTagName() + "标签已存在");
        // 添加新标签
        BTag newTag = BTag.builder()
                .tagName(tag.getTagName())
                .build();
        baseMapper.insert(newTag);
    }

    @Override
    public void deleteTag(List<Integer> tagIdList) {
        // 标签下是否有内容
        Long count = tagTextMapper.selectCount(new LambdaQueryWrapper<BTagText>()
                .in(BTagText::getTagId, tagIdList));
        Assert.isFalse(count > 0, "删除失败，标签下存在内容");
        // 批量删除标签
        tagMapper.deleteBatchIds(tagIdList);
    }

    @Override
    public void updateTag(TagDTO tag) {
        // 标签是否存在
        BTag existTag = tagMapper.selectOne(new LambdaQueryWrapper<BTag>()
                .select(BTag::getId)
                .eq(BTag::getTagName, tag.getTagName()));
        Assert.isNull(existTag, tag.getTagName() + "标签已存在");
        // 修改标签
        BTag newTag = BTag.builder()
                .id(tag.getId())
                .tagName(tag.getTagName())
                .build();
        baseMapper.updateById(newTag);
    }

    @Override
    public List<TagOptionVO> listTagOption() {
        return tagMapper.selectTagOptionList();
    }

    @Override
    public List<TagOptionVO> listRTagOption() {
        return tagMapper.selectRTagOptionList();
    }

    @Override
    public List<TagOptionVO> listQTagOption() {
        return tagMapper.selectQTagOptionList();
    }

    @Override
    public List<TagRecordVO> listTagRVO() {
        return tagMapper.selectTagRVOList();
    }

    @Override
    public List<TagQuizVO> listTagQVO() {
        return tagMapper.selectTagQVOList();
    }

    @Override
    public RecordConditionList listRecordTag(ConditionDTO condition) {
        List<RecordConditionVO> recordConditionList = recordMapper.listRecordByCondition(condition);
        List<String> tagNames = getTagNames(condition);
        return RecordConditionList.builder()
                .recordConditionVOList(recordConditionList)
                .tagNames(tagNames)
                .build();
    }

    @Override
    public QuizConditionList listQuizTag(ConditionDTO condition) {
        List<QuizConditionVO> quizConditionList = quizMapper.listQuizByCondition(condition);
        List<String> tagNames = getTagNames(condition);
        return QuizConditionList.builder()
                .quizConditionVOList(quizConditionList)
                .tagNames(tagNames)
                .build();
    }

    /**
     * 根据标签ids获取标签名
     *
     * @param condition 条件
     * @return 标签名
     */
    private List<String> getTagNames(ConditionDTO condition) {
        List<BTag> bTags = tagMapper.selectList(new LambdaQueryWrapper<BTag>()
                .select(BTag::getTagName)
                .in(BTag::getId, condition.getTagIds()));
        List<String> tagNames = new ArrayList<>();
        if (StringUtils.isNotEmpty(bTags)) {
            bTags.forEach(
                    bTag -> tagNames.add(bTag.getTagName())
            );
        }
        return tagNames;
    }

    /**
     * 覆盖标签生成
     *
     * @param tagNameList 标签名列表
     */
    public List<Integer> getCoverTag(List<String> tagNameList) {
        // 查询出已存在的标签
        List<BTag> existTagList = tagMapper.selectTagList(tagNameList);
        List<String> existTagNameList = existTagList.stream()
                .map(BTag::getTagName)
                .toList();
        List<Integer> existTagIdList = existTagList.stream()
                .map(BTag::getId)
                .collect(Collectors.toList());
        // 移除已存在的标签列表
        tagNameList.removeAll(existTagNameList);
        // 有新标签
        if (StringUtils.isNotEmpty(tagNameList)) {
            // 新标签列表
            List<BTag> newTagList = tagNameList.stream()
                    .map(item -> BTag.builder()
                            .tagName(item)
                            .build())
                    .toList();
            // 批量保存新标签
            newTagList.forEach(item -> {
                tagMapper.insert(item);
            });
            // 获取新标签id列表
            List<Integer> newTagIdList = newTagList.stream()
                    .map(BTag::getId)
                    .toList();
            // 新标签id添加到已有标签的id列表
            existTagIdList.addAll(newTagIdList);
        }
        return existTagIdList;
    }
}